﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectAndMetadata
{
    public class ReflectMemberInfo
    {
        public void ShowMemberInfo()
        {
            MemberInfo[] infos = typeof(Walnut).GetMembers();
            Console.WriteLine("全部成员");
            foreach (var value in infos)
            {
                Console.WriteLine(value);
            }
            Console.WriteLine("方法成员");
            MemberInfo[] infos2 = typeof(Walnut).GetMethods();
            foreach (var value in infos2)
            {
                Console.WriteLine(value);
            }
        }

        public void GetMethod()
        {
            MethodInfo m = typeof(Walnut).GetMethod("Crack");
            Console.WriteLine(m);
            Console.WriteLine(m.ReturnType);
        }

        public void GetGenericTypeMember()
        {
            PropertyInfo[] unbounds = typeof(IEnumerator<>).GetProperties();
            foreach (var value in unbounds)
            {
                Console.WriteLine(value);
            }
            PropertyInfo unbound = typeof(IEnumerator<>).GetProperty("Current");
            PropertyInfo closed = typeof(IEnumerator<int>).GetProperty("Current");

            Console.WriteLine(unbound);   // T Current
            Console.WriteLine(closed);    // Int32 Current

            Console.WriteLine(unbound.PropertyType.IsGenericParameter);  // True
            Console.WriteLine(closed.PropertyType.IsGenericParameter);   // False


            PropertyInfo unbound2 = typeof(List<>).GetProperty("Count");
            PropertyInfo closed2 = typeof(List<int>).GetProperty("Count");

            Console.WriteLine(unbound2);   // Int32 Count
            Console.WriteLine(closed2);    // Int32 Count

            Console.WriteLine(unbound2 == closed2);   // False

            Console.WriteLine(unbound2.DeclaringType.IsGenericTypeDefinition); // True
            Console.WriteLine(closed2.DeclaringType.IsGenericTypeDefinition); // False

        }

        public void DynamicInvokeMember()
        {
            object s = "Hello";
            PropertyInfo prop = s.GetType().GetProperty("Length");
            int length = (int)prop.GetValue(s, null);
            Console.WriteLine(length);
        }

        public void DynamicInvokeMethodParameters()
        {

            Type type = typeof(string);
            Type[] parameterTypes = { typeof(int) };
            MethodInfo method = type.GetMethod("Substring", parameterTypes);
            ParameterInfo[] paramList = method.GetParameters();
            foreach (ParameterInfo x in paramList)
            {
                Console.WriteLine(x.Name);                 // startIndex
                Console.WriteLine(x.ParameterType);        // System.Int32
            }
            object[] arguments = { 2};
            object returnValue = method.Invoke("stamp", arguments);
            Console.WriteLine(returnValue);                           // "amp"
        }

    }

    class Walnut
    {
        private bool cracked;
        public void Crack()
        {
            cracked = true;
        }

        public string Name
        {
            get;
            set;
        }
    }
}
